home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS03.ADF / C / error.c < prev    next >
Text File  |  1986-04-02  |  10KB  |  328 lines

  1. /************************************************************************
  2.  * Error.c --  This program is intended to work with the Lattice C compiler.
  3.  *
  4.  *             Copyright (c) 1986 by Scott Ballantyne.
  5.  *             Free distribution encouraged, commercial sales of this
  6.  *             program or source not allowed.
  7.  *
  8.  *             Error's sole function in life is to merge a source listing
  9.  *             with the error file generated by the first pass of the
  10.  *             of the compiler (LC1). It will then enter ED, and ed will
  11.  *             bring in the merged file.
  12.  *             To use, first compile a file with LC1 as follows:
  13.  *             LC1 >errorfile sourcefile.
  14.  *             This will compile the source, and leave the errors in file
  15.  *             errorfile. If you type LC1 >sourcefile.e sourcefile
  16.  *             then when you run Error, the error file will be replaced
  17.  *             with the contents of the merged file.
  18.  *             Error will create a new file in the same directory as the
  19.  *             source. The newfile will have a .e appended.
  20.  *             If your source file was named file.c the merged file is
  21.  *             called file.e
  22.  *             Once the merge is completed, Error will run ED and ed will
  23.  *             bring in your source.
  24.  *             The error(s) appear directly before the line they reference.
  25.  *             They are included as comments, so the source may be
  26.  *             recompiled without having to delete the extra stuff. 
  27.  *             This program expects a file in the following format:
  28.  *             2 lines of header
  29.  *             N lines of error messages consisting of
  30.  *             sourcefile.c line_number message
  31.  *             This format is the one currently generated by LC1.
  32.  * Compiling:
  33.  *             Compile as usual, but linking with Astartup.obj will
  34.  *             result in a much smaller file size. Recommended.
  35.  * Bugs:       Bug in Execute() causes a small loss of memory.
  36.  *************************************************************************/
  37.  
  38. #include <exec/types.h>
  39. #include <exec/exec.h>
  40. #include <libraries/dos.h>
  41. #include <libraries/dosextens.h>
  42.  
  43. #define  PATH_SIZE      80    /* Just in case - for those long paths */
  44. #define  HEADER         2     /* Lines of copyright stuff to skip */
  45.  
  46. #define  NO_MORE_LINES  -1    /* Flag for end of file */
  47. #define  REST           -2    /* NO_MORE_LINES - 1 */
  48. #define  NO_GO           0    /* AmigaDOS couldn't do it */
  49.  
  50. #define  BREAKP          SetSignal(0, 0) && SIGBREAKF_CTRL_C
  51. /* Resource control */
  52. #define ERROR_BUFFER 0x01
  53. #define SOURCE_FILE  0x02
  54. #define DESTIN_FILE  0x04
  55. #define TERMNL_FILE  0x08
  56. BYTEBITS resources = 0;
  57.  
  58. TEXT  *errbuf;             /* Pointer to current character of error file. */
  59. TEXT  *limit;              /* Pointer to last byte of error file. */
  60. TEXT  *baseptr;
  61. LONG  size;                /* Size of errbuf */
  62. SHORT namlen;              /* Used to skip over source file name in error file. */
  63. LONG  error = 0;           /* Global error return */
  64. TEXT  editor[] = "ed ";    /* Editor entered at program exit */
  65.  
  66. LONG IoErr();
  67. BPTR src, dest, terminal, Open();
  68.  
  69. main(argc, argv)
  70. int argc;
  71. char *argv[];
  72. {
  73.    TEXT  srcnam[PATH_SIZE], destnam[PATH_SIZE];
  74.    TEXT  cmd[PATH_SIZE + sizeof(editor)];  /* Passed to Execute() */
  75.    LONG  getfile(), skip();
  76.    SHORT getname();
  77.    LONG  errlin = 0;             /* Line referenced by error file */
  78.    LONG  srclin = 1;             /* Current line of source  */
  79.  
  80.    if((terminal = Open("*", MODE_OLDFILE)) == NO_GO)
  81.       Exit(IoErr()); /* Panic city... */
  82.    resources |= TERMNL_FILE;
  83.  
  84.    if (argc < 2) {
  85.       error = ERROR_OBJECT_NOT_FOUND;
  86.       AbnormalExit( "Usage: Error NAME\n" );
  87.    }
  88.    if(error = getfile(argv[1]))    /* Reads entire error file to memory */
  89.       AbnormalExit( "Error: Can't open source file\n" );
  90.  
  91.    if(skip(HEADER) == NO_MORE_LINES)   /* Truly abnormal exit, yuk-yuk */
  92.       AbnormalExit( "Error: Congratulations, no compiler errors!\n");
  93.  
  94.    if ((namlen = getname(srcnam, PATH_SIZE)) == 0)
  95.       AbnormalExit( "Error: Source file name error.\n");
  96.  
  97.    strcpy(destnam, srcnam);
  98.    destnam[namlen - 1] = 'e';
  99.    ++namlen;
  100.  
  101.    cmd[0] = '\0';
  102.    strcat(cmd, editor);
  103.    strcat(cmd, destnam);
  104.  
  105.    if ((src = Open(srcnam, MODE_OLDFILE)) == NO_GO) {
  106.       error = IoErr();
  107.       AbnormalExit( "Error: Can't open source file.\n");
  108.    }
  109.   resources |= SOURCE_FILE;
  110.  
  111.    if ((dest = Open(destnam, MODE_NEWFILE)) == NO_GO) {
  112.       error = IoErr();
  113.       AbnormalExit( "Error: Can't open destination file.\n");
  114.    }
  115.    resources |= DESTIN_FILE;
  116.  
  117.    /* Now merge the files */
  118.  
  119.    while(errlin != NO_MORE_LINES || srclin != NO_MORE_LINES) {
  120.       if ( BREAKP )  /* Check for break keypress */
  121.          AbnormalExit("**BREAK\n");
  122.       errlin = get_err_lin();
  123.       srclin = copy(src, dest, srclin, errlin - 1);
  124.       errlin = copy_error(dest, srclin - 1, errlin);
  125.    }
  126. /* Warning! AmigaDOS has a bug in the Execute function. */
  127. /* This bug causes a small loss of memory each time Execute runs. */
  128.    cleanup();  /* Free resources */
  129.    Execute(cmd, NULL, NULL);
  130.    Exit(0);
  131. }
  132.  
  133. AbnormalExit( what_went_wrong )  /* Also normal exit...*/
  134. TEXT *what_went_wrong;
  135. {
  136.    Write(terminal, what_went_wrong, strlen(what_went_wrong));
  137.    cleanup();  /* Release resources */
  138.    Exit(error);
  139. }
  140.  
  141. cleanup()   /* Release resources, but don't exit */
  142. {
  143.    if (resources & SOURCE_FILE)
  144.       Close(src);
  145.    if (resources & DESTIN_FILE)
  146.       Close(dest);
  147.    if (resources & ERROR_BUFFER)
  148.       FreeMem(baseptr, size);
  149.    if (resources & TERMNL_FILE)
  150.       Close(terminal);
  151.    resources = 0;
  152. }
  153.  
  154. LONG getfile(name)  /* Copy error message file to memory. Return error if any */
  155. TEXT *name;
  156. {
  157.    struct FileLock      *lock, *Lock();
  158.    struct FileInfoBlock *fib;
  159.    BPTR  fh;
  160.  
  161.    if ( (lock = Lock(name, ACCESS_READ)) == NO_GO)
  162.       return(IoErr());
  163.    fib = (struct FileInfoBlock *)
  164.         AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC | MEMF_CLEAR);
  165.    if (fib == NULL) {
  166.       UnLock(lock);
  167.       return(ERROR_NO_FREE_STORE);
  168.    }
  169.  
  170.    if (Examine(lock, fib) == NO_GO) {
  171.       error = IoErr();
  172.       FreeMem(fib, sizeof(struct FileInfoBlock));
  173.       UnLock(lock);
  174.       return(error);
  175.    }
  176.    size = fib->fib_Size;
  177.    FreeMem(fib, sizeof(struct FileInfoBlock));
  178.    UnLock(lock);
  179.  
  180.    if ((errbuf = (TEXT *)AllocMem(size, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  181.       return(ERROR_OBJECT_TOO_LARGE);
  182.    resources |= ERROR_BUFFER;
  183.    baseptr = errbuf;
  184.  
  185.    if ((fh = Open(name, MODE_OLDFILE)) == NO_GO)
  186.       return(IoErr());
  187.    if (Read(fh, errbuf, size)== -1) {
  188.       error = IoErr();
  189.       Close(fh);
  190.       return(error);
  191.    }
  192.    limit = errbuf + size;
  193.    Close(fh);
  194.    return(0);
  195. }
  196.  
  197. LONG skip(lines) /* Skip a specified number of lines in error file */
  198. SHORT lines;
  199. {
  200.    SHORT i = 0;
  201.  
  202.    while ( i < lines)
  203.       if (*errbuf++ == '\n')
  204.          i++;
  205.    if (errbuf < limit)
  206.       return(0);
  207.    return(NO_MORE_LINES);
  208. }
  209.  
  210. SHORT getname(name, max)   /* Get file name from error file */
  211. TEXT  *name;
  212. SHORT  max;
  213. {
  214.    SHORT i = 0;
  215.    TEXT  *from = errbuf;   /* Don't want to advance errbuf here */
  216.  
  217.    while ( i < max && (*name++ = *from++) != ' ')
  218.       i++;
  219.    if (i < max && *--name == ' ') {
  220.       *name = '\0';
  221.       return(i);
  222.    }
  223.  
  224.    /* Error return should probably be ERROR_BAD_STREAM_NAME, but this
  225.     * appears to be incorrectly assigned in the dos.h file. Fault returns
  226.     * Invalid window description  for the error code assigned to
  227.     * bad stream name. */
  228.  
  229.    error = ERROR_INVALID_COMPONENT_NAME;
  230.    return(0);
  231. }
  232.  
  233. LONG get_err_lin()   /* Return number of error line, or NO_MORE_LINES */
  234. {
  235.    LONG  atol(), i = 0;
  236.  
  237.    errbuf += namlen;    /* Move past filename at start of line */
  238.  
  239.    if (errbuf >= limit || (i = atol(errbuf)) == 0)
  240.       i = NO_MORE_LINES;
  241.    return(i);
  242. }
  243.  
  244. copy(from, to, start, end)  /* Copy from srcfile to destin file */
  245. BPTR  from, to;
  246. LONG  start, end;  /* Starting line, ending line */
  247. {
  248.    TEXT  tempbuf[512], *tb;
  249.    LONG  what_we_got, lc;
  250.    SHORT count = 0;
  251.  
  252.    if (start == NO_MORE_LINES)
  253.       return(start);
  254.    if (end == REST) {
  255.       while((what_we_got = Read(from, tempbuf, 512)) != 0) {
  256.          if (what_we_got == -1)
  257.             read_error();
  258.          if( Write(to, tempbuf, what_we_got) == -1)
  259.             write_error();
  260.       }
  261.       return(NO_MORE_LINES);
  262.    }
  263.    else {
  264.       for (lc = start; lc <= end && lc != NO_MORE_LINES; lc++  ) {
  265.          tb = tempbuf;
  266.          if ( BREAKP )
  267.             AbnormalExit( "**BREAK\n");
  268.          for(count = 0; count < 512; count++) {
  269.             if ((what_we_got = Read(from, tb++, 1)) != 1) {
  270.                if (what_we_got == 0)   {
  271.                   lc = NO_MORE_LINES - 1;
  272.                   break;
  273.                }
  274.                else
  275.                   read_error();
  276.             }
  277.             if ( *(tb - 1) == '\n')
  278.                break;   /* Got one line */
  279.          }
  280.          if (Write(to, tempbuf, count + 1) == -1)
  281.             write_error();
  282.       }
  283.    }
  284.    return(lc);
  285. }
  286.  
  287. copy_error(to, srcflg, errflg)     /* Copy lines from errbuf to to */
  288. BPTR  to;
  289. LONG  srcflg, errflg;
  290. {
  291.    REGISTER TEXT *eb = errbuf;
  292.  
  293.    if (errflg == NO_MORE_LINES)
  294.       return(errflg);
  295.    while ( *eb++ < '@' && eb < limit)   /* Skip line number. */
  296.       ;
  297.    if (eb-- >= limit)
  298.       return(NO_MORE_LINES);
  299.    if(Write(to, "/* ***", 6) == -1)
  300.       write_error();
  301.    if (srcflg == REST) {
  302.       if ( Write(to, eb, limit - eb) == -1)
  303.          write_error();
  304.       eb = limit;
  305.    }
  306.    else {
  307.       while(*eb != '\n' && eb < limit)
  308.          if (Write(to, eb++, 1) == -1)
  309.             write_error();
  310.    }
  311.    errbuf = ++eb;
  312.    if (Write(to, " */\n", 4) == -1)
  313.       write_error();
  314.    if (errbuf >= limit)
  315.       return(NO_MORE_LINES);
  316.    return(errflg);
  317. }
  318. write_error()  /* Report that a write error occurred. */
  319. {
  320.    error = IoErr();
  321.    AbnormalExit( "Error: Error on write.\n");
  322. }
  323. read_error()   /* Report that a read error occurred.  */
  324. {
  325.    error = IoErr();
  326.    AbnormalExit( "Error: Error on read.\n");
  327. }
  328.